package com.nami.gate.router.utils;

import java.util.concurrent.atomic.AtomicInteger;

public class MessageIdGenerator {
    // 32进制编码的字符集
    private static final char[] BITS = {
        '2', '3', '4', '5', '6', '7', '8', '9',
        'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
        'J', 'K', 'L', 'M', 'N', 'P', 'Q', 'R',
        'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'
    };
    // 自旋ID的上限值
    private static final int SPIN_ID_LIMIT = 0xFFF;
    // 用于生成自旋ID的原子整数
    private static final AtomicInteger INCR = new AtomicInteger(0);

    /**
     * 生成消息ID
     *
     * @param type    会话类型
     * @param sessionId 会话ID
     * @return 消息ID
     */
    public static String generateMessageId(int type, String sessionId) {
        // 生成高64位
        long highBits = createHighBits(type, sessionId);
        // 生成低16位
        long lowBits = createLowBits(sessionId);

        // 将高64位和低16位拼接成80位二进制字符串
        String bitString = Long.toBinaryString(highBits) + Long.toBinaryString(lowBits);

        // 对80位二进制字符串进行32进制编码
        return encodeBitsToChars(bitString);
    }

    /**
     * 创建高64位
     *
     * @param type      会话类型
     * @param sessionId 会话ID
     * @return 高64位
     */
    private static long createHighBits(int type, String sessionId) {
        long highBits = System.currentTimeMillis(); // 获取时间戳
        int spinId = createSpinId(); // 获取自旋ID
        // 依次移位拼接
        highBits = highBits << 12 | spinId;
        highBits = highBits << 4 | (type & 0xF);
        highBits = highBits << 6 | (hash(sessionId) & 0x3F);
        return highBits;
    }

    /**
     * 创建低16位
     *
     * @param sessionId 会话ID
     * @return 低16位
     */
    private static long createLowBits(String sessionId) {
        return hash(sessionId) & 0xFFFF;
    }

    /**
     * 创建自旋ID
     *
     * @return 自旋ID
     */
    private static int createSpinId() {
        int ret = INCR.getAndIncrement();
        if (INCR.get() >= SPIN_ID_LIMIT) {
            INCR.set(0);
        }
        return ret;
    }

    /**
     * 对会话ID进行哈希
     *
     * @param sessionId 会话ID
     * @return 哈希值
     */
    private static long hash(String sessionId) {
        long hash = 0;
        for (char c : sessionId.toCharArray()) {
            hash = (hash * 31 + c) & 0xFFFFFFFFFFFFL; // 取低22位
        }
        return hash;
    }

    /**
     * 将80位二进制字符串进行32进制编码
     *
     * @param bitString 80位二进制字符串
     * @return 编码后的消息ID
     */
    private static String encodeBitsToChars(String bitString) {
        StringBuilder stringBuilder = new StringBuilder();
        for (int i = 0; i < bitString.length(); i += 5) {
            int end = Math.min(i + 5, bitString.length());
            String substring = bitString.substring(i, end);
            int decimalValue = Integer.parseInt(substring, 2);
            char bit = BITS[decimalValue];
            stringBuilder.append(bit);
        }
        return splitAndJoin(stringBuilder.toString(), 4, '-');
    }

    /**
     * 将字符串按指定长度分组并用分隔符连接
     *
     * @param input     输入字符串
     * @param chunkSize 每组长度
     * @param separator 分隔符
     * @return 分组后的字符串
     */
    private static String splitAndJoin(String input, int chunkSize, char separator) {
        StringBuilder output = new StringBuilder();
        int length = input.length();
        if (length == 0) {
            return "";
        }
        for (int i = 0; i < length; i += chunkSize) {
            int end = Math.min(i + chunkSize, length);
            String substring = input.substring(i, end);
            if (output.length() > 0) {
                output.append(separator);
            }
            output.append(substring);
        }
        return output.toString();
    }

    public static void main(String[] args) {
        int conversationType = 1; // 示例会话类型
        String sessionId = "1234567890"; // 示例会话ID
        String messageId = generateMessageId(conversationType, sessionId);
        System.out.println("生成的消息ID: " + messageId);
        //TK6Q-BFHW-222M-HVBD
        //TK6Q-C9QH-222D-HVBD

        //TK6Q-BNQZ-J22M-HVBD
        //TK6Q-BXML-J22M-HVBD
    }
}
